﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;

using Microsoft.Samples.Office.UnifiedCommunications.Gadget.DTO;
using Microsoft.Samples.Office.UnifiedCommunications.Gadget.Events;
using Microsoft.Samples.Office.UnifiedCommunications.Gadget.Config;

using CommunicatorAPI;

namespace Microsoft.Samples.Office.UnifiedCommunications.Gadget
{
    public partial class DesktopContactWindow : Window
    {
        #region Variables

        private static DesktopContactWindow _instance = null;
        private static int _instanceCount = 0;

        private DispatcherTimer _timerNotification = null;
        private ResourceManager _resourceManagerStatusStrings;
        private ResourceManager _resourceManagerStatusColors;

        #endregion

        #region Properties

        public static int InstanceCount { get { return _instanceCount; } }

        public static DesktopContactWindow Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new DesktopContactWindow();
                    _instance.InitializeComponent();
                }
                return _instance;
            }
        }

        public DesktopContact ContactToDisplay
        {
            get { return (DesktopContact)GetValue(ContactToDisplayProperty); }
            set { SetValue(ContactToDisplayProperty, value); }
        }

        public static readonly DependencyProperty ContactToDisplayProperty =
            DependencyProperty.Register(
                "ContactToDisplay",
                typeof(DesktopContact),
                typeof(DesktopContactWindow),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(OnContactToDisplayChanged)));

        private static void OnContactToDisplayChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            (o as DesktopContactWindow).InitializeDesktopContact(e.NewValue as DesktopContact);
        }

        #endregion

        public DesktopContactWindow()
        {
            _instance = this;
            _instanceCount++;

            _resourceManagerStatusStrings = new ResourceManager(
                "Microsoft.Samples.Office.UnifiedCommunications.Gadget.Resources.StatusStrings",
                Assembly.GetExecutingAssembly());

            _resourceManagerStatusColors = new ResourceManager(
                "Microsoft.Samples.Office.UnifiedCommunications.Gadget.Resources.StatusColors",
                Assembly.GetExecutingAssembly());

            InitializeComponent();

            this.MouseDown += new MouseButtonEventHandler(DesktopContactWindow_MouseDown);
            this.MouseEnter += new MouseEventHandler(DesktopContactWindow_MouseEnter);
            this.MouseLeave += new MouseEventHandler(DesktopContactWindow_MouseLeave);
            this.MouseDoubleClick += new MouseButtonEventHandler(DesktopContactWindow_MouseDoubleClick);
            this.Closing += new System.ComponentModel.CancelEventHandler(DesktopContactWindow_Closing);
            this.Unloaded += new RoutedEventHandler(DesktopContactWindow_Unloaded);

            GadgetEventManager.Instance.PresenceStatusChangedEvent += new EventHandler(Instance_PresenceStatusChangedEvent);
            GadgetEventManager.Instance.DesktopContactChangedEvent += new EventHandler(Instance_DesktopContactChangedEvent);
            GadgetEventManager.Instance.ApplicationUnloadedEvent += new EventHandler(Instance_ApplicationUnloadedEvent);

            this.ShowInTaskbar = false;
            this.Topmost = true;

            this.Opacity = Double.Parse(ConfigurationManager.AppSettings["DefaultDesktopContactWindowOpacity"]);
        }

        #region Loading

        void Window_Loaded(object sender, RoutedEventArgs e) {}

        void InitializeDesktopContact(DesktopContact desktopContact) 
        {
            personaContact.SipUri = desktopContact.SipUri;
            txtName.Text = desktopContact.DisplayName;

            this.Title = desktopContact.DisplayName;
        }

        void Instance_DesktopContactChangedEvent(object sender, EventArgs e)
        {
            DesktopContactChangedEventArgs args = e as DesktopContactChangedEventArgs;

            if (args.AffectedContact.SipUri.Equals(this.ContactToDisplay.SipUri))
            {
                if (args.Operation == DesktopContactOperation.Modify)
                {
                    txtName.Text = args.AffectedContact.DisplayName;
                }
                else if (args.Operation == DesktopContactOperation.Remove)
                {
                    Gadget.Instance.UserDesktopContacts.Remove(args.AffectedContact.SipUri);
                    this.Close();
                }
            }
        }

        #endregion

        #region Unloading

        void DesktopContactWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            _instanceCount--;
            Gadget.Instance.PresenceHistoryWindows.Remove(this.ContactToDisplay.SipUri);
        }

        void DesktopContactWindow_Unloaded(object sender, RoutedEventArgs e)
        {
            this.MouseDown -= new MouseButtonEventHandler(DesktopContactWindow_MouseDown);
            this.Closing -= new System.ComponentModel.CancelEventHandler(DesktopContactWindow_Closing);
            this.MouseEnter -= new MouseEventHandler(DesktopContactWindow_MouseEnter);
            this.MouseLeave -= new MouseEventHandler(DesktopContactWindow_MouseLeave);

            GadgetEventManager.Instance.PresenceStatusChangedEvent -= new EventHandler(Instance_PresenceStatusChangedEvent);
            GadgetEventManager.Instance.DesktopContactChangedEvent -= new EventHandler(Instance_DesktopContactChangedEvent);
        }

        void Instance_ApplicationUnloadedEvent(object sender, EventArgs e)
        {
            Gadget.Instance.UserDesktopContacts.Remove(this.ContactToDisplay.SipUri);
            this.Close();
        }

        #endregion

        #region Process Presence Status Updates

        void Instance_PresenceStatusChangedEvent(object sender, EventArgs e)
        {
            PresenceStatusChangedEventArgs args = e as PresenceStatusChangedEventArgs;

            if (args.SipUri.Equals(this.ContactToDisplay.SipUri, StringComparison.OrdinalIgnoreCase))
            {
                User32Utility.BringWindowToTop(
                    Gadget.Instance.UserDesktopContacts[this.ContactToDisplay.SipUri]);

                ShowNotification(_resourceManagerStatusStrings.GetString(args.Status.ToString()));
                ShowNotificationVisualCue(args.Status);

                // Log presence event
                //
                GadgetConfigurationManager.AddPresenceEvent(args.SipUri, DateTime.Now,
                    _resourceManagerStatusStrings.GetString(args.Status.ToString()));

                // Handle another potential presence status change during the timer interval
                //
                if (_timerNotification != null) 
                {
                    _timerNotification.Stop();
                }

                _timerNotification = new DispatcherTimer(
                    TimeSpan.FromSeconds(10), // Show the notification for 10 seconds
                    DispatcherPriority.Input,
                    timerNotification_Tick,
                    this.Dispatcher);

                _timerNotification.Start();
            }
        }

        void timerNotification_Tick(object sender, EventArgs argz)
        {
            ShowNotification(null);
        }

        #endregion

        #region Other UI Functionality

        void DesktopContactWindow_MouseDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                this.DragMove();
            }
            catch
            {

            }
        }

        void DesktopContactWindow_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (Gadget.Instance.PresenceHistoryWindows.IndexOf(this.ContactToDisplay.SipUri) == -1)
            {
                PresenceHistory presenceHistory = new PresenceHistory();
                presenceHistory.ContactToDisplay = this.ContactToDisplay;
                presenceHistory.Owner = this;
                presenceHistory.Show();

                Gadget.Instance.PresenceHistoryWindows.Add(this.ContactToDisplay.SipUri);
            }
        }

        void ShowNotification(string message)
        {
            if (!String.IsNullOrEmpty(message))
            {
                gridNotification.Visibility = Visibility.Visible;
                txtNotification.Text = message;
            }
            else
            {
                txtNotification.Text = string.Empty;
                gridNotification.Visibility = Visibility.Collapsed;
            }
        }

        void ShowNotificationVisualCue(MISTATUS status)
        {
            var brush = new SolidColorBrush();
            brush.Color = ColorUtility.GetColorBrush(_resourceManagerStatusColors.GetString(status.ToString()));
            rectangleNotification.Fill = brush;
        }

        void DesktopContactWindow_MouseLeave(object sender, MouseEventArgs e)
        {
            this.Opacity = Double.Parse(ConfigurationManager.AppSettings["DefaultDesktopContactWindowOpacity"]);
        }

        void DesktopContactWindow_MouseEnter(object sender, MouseEventArgs e)
        {
            this.Opacity = 1;
        }

        #endregion
    }
}
